import {
  SplitScreen1,
  SplitScreen2,
  SplitScreen3,
  SplitScreen4,
  SplitScreen5,
} from '@/components/Icons';
import LivePlayer from '@/components/LivePlayer';
import { createLive, deleteLive, getLiveClients } from '@/services/PeerSerivce';
import { setActive } from '@/services/PreviewService';
import { saveScreenshot } from '@/services/SourceSerivce';
import { DeviceType, InputSourceConfig, OutputSourceConfig } from '@/types';
import { ModalForm, ProFormText } from '@ant-design/pro-form';
import { useModel } from '@umijs/max';
import { Menu, Modal, message } from 'antd';
import { useEffect, useRef, useState } from 'react';
import { useDrag, useDrop } from 'react-dnd';
import SVG from 'react-inlinesvg';
import styles from './style.less';

/**
 * 拖拽项
 * @param config
 * @param onChangeFuse
 * @param onChangePutInWorkerName
 */
const DragItem = ({
  config,
  onChangeFuse,
  onChangePutInWorkerName,
}: {
  config: InputSourceConfig;
  onChangeFuse: (fuse: boolean) => void;
  onChangePutInWorkerName: (putInWorkerName?: string) => void;
}) => {
  const [{ isDragging }, drag] = useDrag(() => ({
    type: 'item',
    item: { ...config },
    collect: (monitor) => ({
      isDragging: monitor.isDragging(),
      handlerId: monitor.getHandlerId(),
    }),
  }));

  const opacity = isDragging ? 0.4 : 1;

  useEffect(() => {
    if (isDragging) {
      onChangeFuse(true);
      onChangePutInWorkerName(config.workerName);
    } else {
      onChangeFuse(false);
    }
  }, [isDragging]);

  return (
    <div ref={drag} style={{ width: '100%', height: '100%', opacity }}>
      {config.label}
    </div>
  );
};
/**
 * 拖拽容器
 */
export const DropContainer = ({
  onDrop,
}: {
  onDrop: (config: InputSourceConfig) => void;
}) => {
  const [{ canDrop, isOver }, drop] = useDrop(() => ({
    accept: 'item',
    drop: (item: InputSourceConfig) => {
      onDrop(item);
      return item;
    },
    collect: (monitor) => ({
      isOver: monitor.isOver(),
      canDrop: monitor.canDrop(),
    }),
  }));

  const isActive = canDrop && isOver;
  let color = '#000';
  if (isActive) {
    color = 'darkgreen';
  } else if (canDrop) {
    color = '#000';
  }

  return (
    <div
      className={styles.dropTitleWrap}
      ref={drop}
      style={{ color }}
      data-testid="dustbin"
    >
      <p className={styles.dropTitle}>
        {isActive ? '松开放入' : '拖拽到此处放入'}
      </p>
    </div>
  );
};

type CreatedLive = {
  liveTitle: string;
  lecturer: string;
  password: string;
  peerId: string;
  [key: string]: any;
};
const LeftInput = ({
  config,
  onChangeFuse,
  onChangePutInWorkerName,
}: {
  config?: OutputSourceConfig;
  onChangeFuse: (fuse: boolean) => void;
  onChangePutInWorkerName: (putInWorkerName?: string) => void;
}) => {
  const [liveData, setLiveData] = useState<CreatedLive>();
  const { initialState } = useModel('@@initialState');
  const { enabledInputSourceConfigs, reloadInputSourceConfigs } =
    useModel('inputSource');
  const { peerId, peerServer } = useModel('global');
  const { patient } = useModel('patient');
  const [_message, contextHolder] = message.useMessage();
  const [_modal, contextHolder1] = Modal.useModal();

  useEffect(() => {
    reloadInputSourceConfigs();
    getLiveClients(peerServer).then((data) => {
      if (data[peerId]) {
        setLiveData(data[peerId]);
      }
    });
  }, []);

  const handleCreateLive = async (data: CreatedLive) => {
    const liveData = {
      ...data,
      peerId,
      ...patient,
      streamName: config?.streamName,
    };
    const { success } = await createLive(peerServer, liveData);
    if (success) {
      _message.success('开始直播成功');
    } else {
      _message.success('开始直播失败');
    }
    setLiveData(liveData);
    return success;
  };

  return (
    <div className={styles.leftInput}>
      {contextHolder}
      {contextHolder1}
      <div className={styles.title}>输入源</div>
      <Menu
        selectedKeys={[]}
        style={{ width: 256 }}
        mode="inline"
        items={[
          ...enabledInputSourceConfigs.map((v: InputSourceConfig) => ({
            key: v.workerName,
            label: (
              <div
                style={{ width: '100%', height: '100%' }}
                draggable={true}
                onDragStart={() => {
                  onChangeFuse(true);
                  onChangePutInWorkerName(v.workerName);
                }}
                onDragEnd={() => {
                  onChangeFuse(false);
                }}
              >
                <DragItem
                  config={v}
                  onChangeFuse={onChangeFuse}
                  onChangePutInWorkerName={onChangePutInWorkerName}
                />
              </div>
            ),
          })),
        ]}
      />
      <div
        className={styles.control}
        style={{ display: config ? 'flex' : 'none' }}
      >
        <div className={styles.panel}>
          <div className={styles.liveTitle}>
            <div className={styles.title1}>直播标题：</div>
            <div className={styles.value}>{liveData?.liveTitle}</div>
          </div>
          <div className={styles.liveTitle}>
            <div className={styles.title1}>讲&emsp;&emsp;师：</div>
            <div className={styles.value1}>{liveData?.lecturer}</div>
          </div>
          <div className={styles.liveTitle}>
            <div className={styles.title1}>密&emsp;&emsp;码：</div>
            <div className={styles.value1}>{liveData?.password}</div>
          </div>

          {liveData != null ? (
            <div
              className={styles.btn}
              onClick={async () => {
                _modal.confirm({
                  centered: true,
                  content: '确定结束直播吗？',
                  okText: '确定',
                  cancelText: '取消',
                  async onOk() {
                    const { success } = await deleteLive(peerServer, peerId);
                    if (success) {
                      _message.success('结束直播成功');
                      setLiveData(undefined);
                    } else {
                      _message.success('结束直播失败');
                    }
                  },
                });
              }}
            >
              结束直播
            </div>
          ) : (
            <ModalForm<CreatedLive>
              initialValues={{
                liveTitle: `${initialState?.nickname}的直播间`,
                lecturer: '',
                password: '',
              }}
              width={400}
              title="开始直播"
              trigger={<div className={styles.btn}>开始直播</div>}
              modalProps={{
                centered: true,
              }}
              autoFocusFirstInput
              onFinish={handleCreateLive}
            >
              <ProFormText
                name="liveTitle"
                label="直播标题"
                rules={[{ required: true }]}
              />
              <ProFormText name="lecturer" label="讲师" />
              <ProFormText
                name="password"
                label="密码（密码为空不加密直播间）"
              />
            </ModalForm>
          )}
        </div>
      </div>
    </div>
  );
};

const CenterVideo = ({
  config,
  putInWorkerName,
  onChangePutInWorkerName,
  fuse,
}: {
  config?: OutputSourceConfig;
  putInWorkerName?: string;
  fuse: boolean;
  onChangePutInWorkerName: (putInWorkerName?: string) => void;
}) => {
  const [_message, contextHolder2] = message.useMessage();
  const { playback, updatePlayback } = useModel('outputSource');
  const { recording, startRecord, stopRecord } = useModel('record');
  const { initialState } = useModel('@@initialState');
  const { videoMatrixServer } = useModel('global');
  const ref = useRef<HTMLDivElement>(null);

  const onDrop = (index: number, workerName: string = putInWorkerName!) => {
    playback(workerName, index, config as OutputSourceConfig);
    onChangePutInWorkerName(undefined);
  };

  useEffect(() => {
    const listener = () => {
      if (ref.current) {
        const height = ref.current.parentElement!.clientWidth * (9 / 16);
        if (height > ref.current.parentElement!.clientHeight) {
          const width = ref.current.parentElement!.clientHeight * (16 / 9);
          ref.current.style.width = width + 'px';
        } else {
          ref.current.style.height = height + 'px';
        }
      }
    };
    listener();
    window.addEventListener('resize', listener);
    return () => {
      window.removeEventListener('resize', listener);
    };
  }, []);

  return (
    <div className={styles.centerVideo}>
      {contextHolder2}
      <div className={styles.videoWrapper}>
        <div
          className={styles.video}
          style={{ display: config ? 'unset' : 'none' }}
          ref={ref}
        >
          <LivePlayer
            type="SRS_WebRTC"
            controls={false}
            visible={true}
            cache={true}
            server={initialState!.videoMatrixIp!}
            streamKey="stream"
          />
          {fuse && (
            <div className={styles.fuseBarr}>
              {config?.splitScreenMode && (
                <div
                  className={[
                    styles.previewDrop,
                    // isNotBlank(putInSourceName!) ? styles.active : '',
                  ].join(' ')}
                >
                  {config.splitScreenMode === '1x1' && (
                    <div
                      className={styles._1x1}
                      onDragOver={(ev) => ev.preventDefault()}
                      onDrop={() => onDrop(0)}
                    >
                      <DropContainer
                        onDrop={({ workerName }) => onDrop(0, workerName)}
                      />
                    </div>
                  )}
                  {config.splitScreenMode === '1x2' && (
                    <>
                      <div
                        className={styles._1x2}
                        onDragOver={(ev) => ev.preventDefault()}
                        onDrop={() => onDrop(0)}
                      >
                        <DropContainer
                          onDrop={({ workerName }) => onDrop(0, workerName)}
                        />
                      </div>
                      <div
                        className={styles._1x2}
                        onDragOver={(ev) => ev.preventDefault()}
                        onDrop={() => onDrop(1)}
                      >
                        <DropContainer
                          onDrop={({ workerName }) => onDrop(1, workerName)}
                        />
                      </div>
                    </>
                  )}
                  {config.splitScreenMode === '2x2' && (
                    <>
                      <div
                        className={styles._2x2}
                        onDragOver={(ev) => ev.preventDefault()}
                        onDrop={() => onDrop(0)}
                      >
                        <DropContainer
                          onDrop={({ workerName }) => onDrop(0, workerName)}
                        />
                      </div>
                      <div
                        className={styles._2x2}
                        onDragOver={(ev) => ev.preventDefault()}
                        onDrop={() => onDrop(1)}
                      >
                        <DropContainer
                          onDrop={({ workerName }) => onDrop(1, workerName)}
                        />
                      </div>
                      <div
                        className={styles._2x2}
                        onDragOver={(ev) => ev.preventDefault()}
                        onDrop={() => onDrop(2)}
                      >
                        <DropContainer
                          onDrop={({ workerName }) => onDrop(2, workerName)}
                        />
                      </div>
                      <div
                        className={styles._2x2}
                        onDragOver={(ev) => ev.preventDefault()}
                        onDrop={() => onDrop(3)}
                      >
                        <DropContainer
                          onDrop={({ workerName }) => onDrop(3, workerName)}
                        />
                      </div>
                    </>
                  )}
                  {config.splitScreenMode === 'LEFT1xRIGHT3' && (
                    <>
                      <div
                        className={styles._LEFT1xRIGHT3}
                        onDragOver={(ev) => ev.preventDefault()}
                        onDrop={() => onDrop(0)}
                      >
                        <DropContainer
                          onDrop={({ workerName }) => onDrop(0, workerName)}
                        />
                      </div>
                      <div
                        className={styles._LEFT1xRIGHT3}
                        onDragOver={(ev) => ev.preventDefault()}
                        onDrop={() => onDrop(1)}
                      >
                        <DropContainer
                          onDrop={({ workerName }) => onDrop(1, workerName)}
                        />
                      </div>
                      <div
                        className={styles._LEFT1xRIGHT3}
                        onDragOver={(ev) => ev.preventDefault()}
                        onDrop={() => onDrop(2)}
                      >
                        <DropContainer
                          onDrop={({ workerName }) => onDrop(2, workerName)}
                        />
                      </div>
                      <div
                        className={styles._LEFT1xRIGHT3}
                        onDragOver={(ev) => ev.preventDefault()}
                        onDrop={() => onDrop(3)}
                      >
                        <DropContainer
                          onDrop={({ workerName }) => onDrop(3, workerName)}
                        />
                      </div>
                    </>
                  )}
                  {config.splitScreenMode === 'LEFT1xRIGHT_BOTTOM1' && (
                    <>
                      <div
                        className={styles._LEFT1xRIGHT_BOTTOM1}
                        onDragOver={(ev) => ev.preventDefault()}
                        onDrop={() => onDrop(0)}
                      >
                        <DropContainer
                          onDrop={({ workerName }) => onDrop(0, workerName)}
                        />
                      </div>
                      <div
                        className={styles._LEFT1xRIGHT_BOTTOM1}
                        onDragOver={(ev) => ev.preventDefault()}
                        onDrop={() => onDrop(1)}
                      >
                        <DropContainer
                          onDrop={({ workerName }) => onDrop(1, workerName)}
                        />
                      </div>
                    </>
                  )}
                </div>
              )}
            </div>
          )}
        </div>
        <div style={{ display: config ? 'none' : 'unset' }}>
          未配置直播输出设备，无法使用
        </div>
      </div>
      <div className={styles.toolBar}>
        <div className={styles.startRongPing}>
          <div
            title={recording ? '停止录制' : '开始录制'}
            className={[styles.toolIcon, recording ? styles.active1 : ''].join(
              ' ',
            )}
            onClick={() => {
              if (recording) {
                stopRecord(_message);
              } else {
                startRecord(_message);
              }
            }}
          >
            <SVG className={styles.toolIconSvg} src="/img/source/录制.svg" />
          </div>
          <div
            title="截图"
            className={styles.toolIcon}
            onClick={async () => {
              const result = await saveScreenshot(
                videoMatrixServer,
                config!.workerName!,
              );
              if (result.success) {
                _message.success('截图成功');
              } else {
                _message.error('截图失败');
              }
              // console.log(result);
            }}
          >
            <SVG className={styles.toolIconSvg} src="/img/source/截图.svg" />
          </div>
        </div>
        <div className={styles.splitScreen}>
          <div
            className={[
              styles.toolIcon,
              config?.splitScreenMode === '1x1' ? styles.active : '',
            ].join(' ')}
            onClick={() => {
              if (config) {
                config.splitScreenMode = '1x1';
                updatePlayback(config as OutputSourceConfig);
              }
            }}
          >
            <SplitScreen1 active={config?.splitScreenMode === '1x1'} />
          </div>
          <div
            className={[
              styles.toolIcon,
              config?.splitScreenMode === '1x2' ? styles.active : '',
            ].join(' ')}
            onClick={() => {
              if (config) {
                config.splitScreenMode = '1x2';
                updatePlayback(config as OutputSourceConfig);
              }
            }}
          >
            <SplitScreen2 active={config?.splitScreenMode === '1x2'} />
          </div>
          <div
            className={[
              styles.toolIcon,
              config?.splitScreenMode === '2x2' ? styles.active : '',
            ].join(' ')}
            onClick={() => {
              if (config) {
                config.splitScreenMode = '2x2';
                updatePlayback(config as OutputSourceConfig);
              }
            }}
          >
            <SplitScreen3 active={config?.splitScreenMode === '2x2'} />
          </div>
          <div
            className={[
              styles.toolIcon,
              config?.splitScreenMode === 'LEFT1xRIGHT3' ? styles.active : '',
            ].join(' ')}
            onClick={() => {
              if (config) {
                config.splitScreenMode = 'LEFT1xRIGHT3';
                updatePlayback(config as OutputSourceConfig);
              }
            }}
          >
            <SplitScreen4 active={config?.splitScreenMode === 'LEFT1xRIGHT3'} />
          </div>

          <div
            className={[
              styles.toolIcon,
              config?.splitScreenMode === 'LEFT1xRIGHT_BOTTOM1'
                ? styles.active
                : '',
            ].join(' ')}
            onClick={() => {
              if (config) {
                config.splitScreenMode = 'LEFT1xRIGHT_BOTTOM1';
                updatePlayback(config as OutputSourceConfig);
              }
            }}
          >
            <SplitScreen5
              active={config?.splitScreenMode === 'LEFT1xRIGHT_BOTTOM1'}
            />
          </div>
        </div>
        <div className={styles.stopRongPing}>
          <div
            title="清除融屏"
            className={styles.toolIcon}
            onClick={() => {
              if (config) {
                config.splitScreenMode = '1x1';
                config.previewConfig = [
                  undefined,
                  undefined,
                  undefined,
                  undefined,
                ];
                updatePlayback(config as OutputSourceConfig);
              }
            }}
          >
            <SVG className={styles.toolIconSvg} src="/img/split/清空资源.svg" />
          </div>
        </div>
      </div>
    </div>
  );
};

export default () => {
  const [fuse, setFuse] = useState(false);
  const [putInWorkerName, setPutInWorkerName] = useState<string>();
  const [config, setConfig] = useState<OutputSourceConfig>();
  const { enabledOutputSourceConfigs, reloadOutputSourceConfigs } =
    useModel('outputSource');
  const { videoMatrixServer } = useModel('global');

  useEffect(() => {
    reloadOutputSourceConfigs();
  }, []);

  useEffect(() => {
    if (!fuse) {
      setPutInWorkerName(undefined);
    }
  }, [fuse]);

  useEffect(() => {
    for (let enabledOutputSourceConfig of enabledOutputSourceConfigs) {
      if (enabledOutputSourceConfig.deviceType === DeviceType.StreamOutput) {
        setConfig(enabledOutputSourceConfig);
        setActive(videoMatrixServer, enabledOutputSourceConfig.workerName!);
        break;
      }
    }
  }, [enabledOutputSourceConfigs]);

  return (
    <div className={styles.videoRouting}>
      <LeftInput
        config={config}
        onChangeFuse={setFuse}
        onChangePutInWorkerName={setPutInWorkerName}
      />
      <CenterVideo
        config={config}
        putInWorkerName={putInWorkerName}
        fuse={fuse}
        onChangePutInWorkerName={setPutInWorkerName}
      />
    </div>
  );
};
